home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / plan / src / sublist.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  6KB  |  230 lines

  1. /*
  2.  * sublist management: a sublist is an array of pointer pointing to
  3.  * specific entries in the master list (see dbase.c), for example all
  4.  * entries on the same day. These extractions are done here.
  5.  * Returns pointer to sublist, or 0 if there are no entries.
  6.  *
  7.  *    create_sublist(list, w)
  8.  *    destroy_sublist(w)
  9.  *
  10.  */
  11.  
  12. #ifndef MIPS
  13. #include <stdlib.h>
  14. #endif
  15. #include <ctype.h>
  16. #include <string.h>
  17. #include <Xm/Xm.h>
  18. #include "cal.h"
  19.  
  20. #define CHUNK        100            /* sublist allocation unit */
  21.  
  22. extern char        *mystrdup();
  23. #if defined(SUN) && !defined(SOLARIS2)
  24. #define regcmp re_comp
  25. #define regex re_exec
  26. #endif
  27. #ifdef linux
  28. #define regcmp regcomp
  29. #define regex regexec
  30. #endif
  31. #ifndef NOREGEX
  32. extern char        *regcmp(), *regex(), *__loc1;
  33. #endif
  34. extern int        search_mode;        /* 0=case, 1=lit, 2=regex */
  35. static            append_entry();
  36. static BOOL        keymatch();
  37. extern BOOL        lookup_entry(), lookup_next_entry();
  38.  
  39.  
  40. /*
  41.  * create a sublist that describes the contents of a list menu. A sublist
  42.  * is an array of pointers to schedule entries (which live in the main list).
  43.  * The sublist is put into the rows of the list menu in order, but there
  44.  * are usually more menu rows than sublist entry pointers (so we have a
  45.  * few blank rows for new input).
  46.  * This routine is called whenever a list menu is created, and whenever an
  47.  * entry changes in any way. That isn't very efficient if the main list has
  48.  * hundreds or thousands of entries, so this may change in future versions.
  49.  */
  50.  
  51. create_sublist(list, w)
  52.     register struct list    *list;        /* main list with all entries*/
  53.     struct listmenu        *w;        /* menu we are doing this for*/
  54. {
  55.     char            *key = w->key;    /* keyword to look for */
  56.     BOOL            found;        /* TRUE if lookup succeeded */
  57.     struct lookup        lookup;        /* result of entry lookup */
  58.     register struct entry    *ep;        /* next entry to check */
  59.     register int        i;        /* entry counter */
  60.  
  61.     list->locked++;
  62.     destroy_sublist(w);                /* zap old list */
  63.     if (w->time) {                    /*--- time range ---*/
  64.         time_t    begin = w->time;
  65.         time_t    end   = w->period ? begin+w->period : begin+86400;
  66.         found = lookup_entry(&lookup, list, begin, TRUE, FALSE);
  67.         while (found && lookup.trigger >= begin
  68.                  && lookup.trigger <  end) {
  69.             append_entry(&w->sublist, &list->entry[lookup.index]);
  70.             found = lookup_next_entry(&lookup);
  71.         }
  72.     } else if (w->key) {                /*--- keywords ---*/
  73.         if (search_mode == 1) {
  74.             register char *k;
  75.             if (!(key = mystrdup(key))) {
  76.                 list->locked--;
  77.                 return;
  78.             }
  79.             for (k=key; *k; k++)
  80.                 if (isupper(*k)) *k = tolower(*k);
  81.         }
  82. #ifndef NOREGEX
  83.         if (search_mode == 2)
  84.             if (!(key = regcmp(key, 0))) {
  85.                 list->locked--;
  86.                 return;
  87.             }
  88. #endif
  89.         for (ep=list->entry, i=0; i < list->nentries; i++, ep++)
  90.             if (ep->message && keymatch(key, ep->message) ||
  91.                 ep->script  && keymatch(key, ep->script ) ||
  92.                 ep->meeting && keymatch(key, ep->meeting) ||
  93.                 ep->note    && keymatch(key, ep->note   ))
  94.                 append_entry(&w->sublist, ep);
  95. #ifndef NOREGEX
  96.         if (search_mode == 2)
  97.             free(key);
  98. #endif
  99.         if (search_mode == 1)
  100.             free(key);
  101.  
  102.     } else if (w->oneentry) {            /*--- one entry --- */
  103.         for (i=0; i < list->nentries; i++)
  104.             if (w->oneentry == &list->entry[i])
  105.                 append_entry(&w->sublist, w->oneentry);
  106.  
  107.     } else {                    /*--- all ---*/
  108.         for (i=0; i < list->nentries; i++)
  109.             append_entry(&w->sublist, &list->entry[i]);
  110.     }
  111.     list->locked--;
  112. }
  113.  
  114.  
  115. /*
  116.  * destroy the sublist of a list menu. De-allocate it, and decrement the
  117.  * entry reference counts.
  118.  */
  119.  
  120. destroy_sublist(w)
  121.     struct listmenu        *w;        /* menu we are doing this for*/
  122. {
  123.     if (w->sublist) {
  124.         free(w->sublist);
  125.         w->sublist = 0;
  126.     }
  127. }
  128.  
  129.  
  130. /*
  131.  * for generating sublist by keyword: return TRUE if the keyword is in the
  132.  * string. This routine is time-critical, it is moderately optimized. It
  133.  * assumes that search strings are short; it could stop scanning earlier.
  134.  * In case insensitive mode, <key> is expected to contain lower case only.
  135.  * In regexp mode, <key> is expected to be a compiled regular expression.
  136.  */
  137.  
  138. static BOOL keymatch(key, string)
  139.     char            *key;        /* keyword to look for */
  140.     char            *string;    /* text to look in */
  141. {
  142.     register char        *p;        /* fast string scan ptr */
  143.     register char        key0 = key[0];    /* first char of key */
  144.     register char        c;        /* temp for case conversion */
  145.     register int        i;        /* scan index */
  146.     register int        len = strlen(key);
  147.  
  148.     switch(search_mode) {
  149.       default:
  150.       case 0:
  151.         for (p=string; *p; p++)
  152.             if (p[0] == key0 &&
  153.                 !strncmp(key+1, p+1, len-1))
  154.                 return(TRUE);
  155.         return(FALSE);
  156.  
  157.       case 1:
  158.         for (p=string; *p; p++) {
  159.             c = p[0];
  160.             if (isupper(c)) c = tolower(c);
  161.             if (c == key0) {
  162.                 for (i=1; i < len; i++) {
  163.                     c = p[i];
  164.                     if (isupper(c)) c = tolower(c);
  165.                     if (c != key[i])
  166.                         break;
  167.                 }
  168.                 if (i == len)
  169.                     return(TRUE);
  170.             }
  171.         }
  172.         return(FALSE);
  173.  
  174. #ifndef NOREGEX
  175.       case 2: {
  176.         char dummy[1024];
  177.         return(regex(key, string,
  178.                 dummy, dummy, dummy, dummy, dummy,
  179.                 dummy, dummy, dummy, dummy, dummy) != 0);
  180.         }
  181. #endif
  182.     }
  183. }
  184.  
  185.  
  186. /*----------------------------- sublist management for use by above routines */
  187. /*
  188.  * append an entry to a sublist. There is no sorting because the main list
  189.  * is sorted and will be scanned in order when a sublist is generated from it.
  190.  * A pointer to a pointer is passed; the pointed-to pointer changes if the
  191.  * list is re-allocated (or allocated for the first time). To start a new
  192.  * list, pass a pointer to a null pointer; to get rid of a list, free() it.
  193.  * Nothing is ever removed from a sublist; it is remade every time.
  194.  */
  195.  
  196. static append_entry(sub, entry)
  197.     struct sublist        **sub;        /* list to append to */
  198.     struct entry        *entry;        /* entry to append */
  199. {
  200.     int            num;        /* # of entries in old list */
  201.     int            size;        /* size of allocated old list*/
  202.     struct sublist        *new;        /* larger list if required */
  203.     register struct entry    **p, **q;    /* entry copy pointers */
  204.     register int        i;        /* entry copy counter */
  205.  
  206.     num  = *sub ? (*sub)->nentries : 0;
  207.     size = *sub ? (*sub)->size     : 0;
  208.     if (num+1 > size) {                /* need larger list */
  209.         size += CHUNK;
  210.         if (!(new = (struct sublist *)malloc(sizeof(struct sublist) +
  211.                       sizeof(struct entry *) * size)))
  212.             fatal("no memory");
  213.         if (!*sub)
  214.             new->nentries = 0;        /* start new list... */
  215.         else {
  216.             new->nentries = num;        /* ...or copy old */
  217.             p = (*sub)->entry;
  218.             q = new->entry;
  219.             for (i=0; i < num; i++)
  220.                 *q++ = *p++;
  221.         }
  222.         new->size = size;
  223.         if (*sub)                /* discard old list */
  224.             free(*sub);
  225.         *sub = new;
  226.     }
  227.     (*sub)->entry[num] = entry;            /* append entry */
  228.     (*sub)->nentries++;
  229. }
  230.